/*
 * This file is part of jboss-admin-rest
 * Copyright 2009, Christos Vasilakis (cvasilak@gmail.com)
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.admin.rest.services;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.jboss.admin.rest.domain.deployments.OperationBean;
import org.jboss.admin.rest.exceptions.BadRequestException;
import org.jboss.admin.rest.exceptions.InternalServerErrorException;
import org.jboss.admin.rest.factory.ProfileServiceFactory;
import org.jboss.deployers.spi.management.deploy.DeploymentManager;
import org.jboss.deployers.spi.management.deploy.DeploymentProgress;
import org.jboss.deployers.spi.management.deploy.DeploymentStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import java.io.File;
import java.net.URL;

public abstract class BaseResource {

	private static final Logger logger = LoggerFactory.getLogger("BaseResource");
	
	protected final static String ANY = "ANY";

	protected Response undeployArtifact(String name) throws InternalServerErrorException {
		DeploymentManager dm = ProfileServiceFactory.getDeploymentManager();

		DeploymentProgress progress;
		DeploymentStatus status;

		try {
			progress = dm.stop(name);
			progress.run();
			status = progress.getDeploymentStatus();

			if (status.isFailed()) {
				throw status.getFailure();
			}

			progress = dm.remove(name);
			progress.run();

			status = progress.getDeploymentStatus();

			if (status.isFailed()) {
				throw status.getFailure();
			}
		} catch (Exception e) {
			throw new InternalServerErrorException(e.getMessage(), e);
		}

		return Response.status(Status.OK).entity("deployment successfully deleted!").build();
	}

	protected Response uploadArtifact(HttpServletRequest request) throws BadRequestException, InternalServerErrorException {
		DiskFileItemFactory factory = new DiskFileItemFactory();

		/* The temp dir is relative to the server profile designated by the
		 * the system property "jboss.server.temp.dir" set by the runtime
		 * (e.g. /opt/jboss-5.1.0.GA/server/default/tmp/jboss-admin-rest/)
		 */
		File tmpDir = new File(System.getProperty("jboss.server.temp.dir"), "jboss-admin-rest");

		// create the temp dir if it doesn't exist (yet).
		if (!tmpDir.exists())
			tmpDir.mkdirs();

		factory.setRepository(tmpDir);
		ServletFileUpload upload = new ServletFileUpload(factory);

		FileItem item;

		try {
			item = (FileItem) upload.parseRequest(request).get(0);
		} catch (FileUploadException e) {
			throw new BadRequestException("failed to upload deployment artifact, check your request!");
		}

		String fileName = item.getName();

		/*
		String fieldName = item.getFieldName();
		String contentType = item.getContentType();
		boolean isInMemory = item.isInMemory();
		long sizeInBytes = item.getSize();
		*/

		try {
			File savedFile = new File(tmpDir, fileName);
			item.write(savedFile);

			DeploymentManager dm = ProfileServiceFactory.getDeploymentManager();

			DeploymentProgress progress;
			DeploymentStatus status;

			URL contentURL = savedFile.toURI().toURL();
			progress = dm.distribute(savedFile.getName(), contentURL, true);
			progress.run();

			status = progress.getDeploymentStatus();
			if (status.isFailed()) {
				throw status.getFailure();
			}

			String[] repositoryNames = progress.getDeploymentID().getRepositoryNames();
			progress = dm.start(repositoryNames);
			progress.run();

			status = progress.getDeploymentStatus();
			if (status.isFailed()) { // deployment is invalid
				// save the exception
				Exception e = status.getFailure();
				// delete artifact from the temporary directory
				savedFile.delete();
				// delete artifact from the "deploy" directory
				progress = dm.remove(repositoryNames);
				progress.run();

				status = progress.getDeploymentStatus();
				if (status.isFailed()) {
					logger.error("failed to remove bogus deployment artifact!");
				}

				// ok throw original exception to inform user
				throw e;
			}

			return Response.status(Status.CREATED).entity("deployment successfully created and started!").build();

		} catch (Exception e) {
			throw new InternalServerErrorException(e.getMessage(), e);
		}
	}

	protected Response updateArtifact(String name, OperationBean operation) throws BadRequestException, InternalServerErrorException {
		if (OperationBean.isInvalid(operation)) {
			throw new BadRequestException("invalid operation, only 'start', 'stop', 'redeploy' is allowed here!");
		}

		try {
			DeploymentManager dm = ProfileServiceFactory.getDeploymentManager();

			DeploymentProgress progress;
			DeploymentStatus status;

			if (operation.getOperType().equals(OperationBean.STOP)) {
				progress = dm.stop(name);

				progress.run();
				status = progress.getDeploymentStatus();

				if (status.isFailed()) {
					throw status.getFailure();
				}
			} else if (operation.getOperType().equals(OperationBean.START)) {
				progress = dm.start(name);
				progress.run();
				status = progress.getDeploymentStatus();

				if (status.isFailed()) {
					throw status.getFailure();
				}
			} else if (operation.getOperType().equals(OperationBean.REDEPLOY)) {
				progress = dm.redeploy(name);
				progress.run();
				status = progress.getDeploymentStatus();

				if (status.isFailed()) {
					throw status.getFailure();
				}
			}
		} catch (Exception e) {
			throw new InternalServerErrorException(e.getMessage(), e);
		}

		return Response.status(Status.OK).entity("deployment operation '" + operation.getOperType() + "' successfully completed!").build();
	}
}
